Skip to content

RetryPolicy: include service name in 401 Unauthorized error messages#1532

Open
offbyone wants to merge 1 commit intomainfrom
o1/push-lqwlqnrruqpk
Open

RetryPolicy: include service name in 401 Unauthorized error messages#1532
offbyone wants to merge 1 commit intomainfrom
o1/push-lqwlqnrruqpk

Conversation

@offbyone
Copy link
Copy Markdown
Contributor

Thread an optional serviceName parameter through RetryPolicy so that 401 Unauthorized errors identify which service/credential failed (e.g. "Unauthorized (Azure DevOps). Please check your token and try again.").

Production factories (GithubApiFactory, AdoApiFactory, AdoPipelineTriggerServiceFactory, BbsApiFactory) now create per-service RetryPolicy instances instead of sharing the DI singleton. Integration tests also wire service names through their manually-constructed clients.

  • Did you write/update appropriate tests
  • Release notes updated (if appropriate)
  • Appropriate logging output
  • Issue linked
  • Docs updated (or issue created)
  • New package licenses are added to ThirdPartyNotices.txt (if applicable)

Copilot AI review requested due to automatic review settings March 27, 2026 15:12
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enhances the shared RetryPolicy so that 401 Unauthorized errors include a service identifier, making credential failures easier to diagnose across the Octoshift CLI’s various source/target integrations.

Changes:

  • Added optional serviceName support to RetryPolicy (plus WithServiceName) and included it in 401 Unauthorized exception messages.
  • Updated production factories (ADO/BBS/GitHub) to create service-tagged RetryPolicy instances for their clients instead of using an untagged singleton.
  • Updated integration tests to pass service-tagged retry policies into manually constructed clients/APIs.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/Octoshift/RetryPolicy.cs Adds service name threading and includes it in 401 Unauthorized messages.
src/Octoshift/Factories/GithubApiFactory.cs Creates a GitHub-tagged retry policy for the GithubClient (but currently not applied consistently to API/uploader).
src/ado2gh/Factories/AdoApiFactory.cs Tags retry policy for Azure DevOps client usage.
src/ado2gh/Factories/AdoPipelineTriggerServiceFactory.cs Tags retry policy for Azure DevOps client usage in pipeline trigger path.
src/bbs2gh/Factories/BbsApiFactory.cs Tags retry policy for Bitbucket Server client usage (basic + kerberos).
src/OctoshiftCLI.IntegrationTests/AdoToGithub.cs Passes tagged retry policies into ADO/GitHub clients/APIs in integration tests.
src/OctoshiftCLI.IntegrationTests/BbsToGithub.cs Passes tagged retry policies into BBS/GitHub clients/APIs in integration tests.
src/OctoshiftCLI.IntegrationTests/GhesToGithub.cs Passes tagged retry policies into GHES/GitHub clients/APIs in integration tests.
src/OctoshiftCLI.IntegrationTests/GithubToGithub.cs Passes tagged retry policies into GitHub client/API in integration tests.
Comments suppressed due to low confidence (2)

src/Octoshift/Factories/GithubApiFactory.cs:60

  • Same issue in the target GitHub factory path: ArchiveUploader and GithubApi are still receiving _retryPolicy instead of the service-tagged clientRetryPolicy, so unauthorized errors from API/uploader retries won't include which service/credential failed. Pass clientRetryPolicy through here as well.
        var clientRetryPolicy = (_retryPolicy ?? new RetryPolicy(_octoLogger)).WithServiceName("GitHub");
        var githubClient = new GithubClient(_octoLogger, _clientFactory.CreateClient("Default"), _versionProvider, clientRetryPolicy, _dateTimeProvider, targetPersonalAccessToken);
        var multipartUploader = new ArchiveUploader(githubClient, uploadsUrl, _octoLogger, _retryPolicy, _environmentVariableProvider);
        return new GithubApi(githubClient, apiUrl, _retryPolicy, multipartUploader);
    }

src/Octoshift/Factories/GithubApiFactory.cs:49

  • Same issue as above: clientRetryPolicy is service-tagged, but _retryPolicy is still passed into ArchiveUploader/GithubApi, so 401 Unauthorized errors originating from those components won't include the service context. Use clientRetryPolicy consistently for the uploader and API instance created here.
        var clientRetryPolicy = (_retryPolicy ?? new RetryPolicy(_octoLogger)).WithServiceName("GitHub");
        var githubClient = new GithubClient(_octoLogger, _clientFactory.CreateClient("NoSSL"), _versionProvider, clientRetryPolicy, _dateTimeProvider, sourcePersonalAccessToken);
        var multipartUploader = new ArchiveUploader(githubClient, uploadsUrl, _octoLogger, _retryPolicy, _environmentVariableProvider);
        return new GithubApi(githubClient, apiUrl, _retryPolicy, multipartUploader);
    }

Comment on lines +34 to 38
var clientRetryPolicy = (_retryPolicy ?? new RetryPolicy(_octoLogger)).WithServiceName("GitHub");
var githubClient = new GithubClient(_octoLogger, _clientFactory.CreateClient("Default"), _versionProvider, clientRetryPolicy, _dateTimeProvider, sourcePersonalAccessToken);
var multipartUploader = new ArchiveUploader(githubClient, uploadsUrl, _octoLogger, _retryPolicy, _environmentVariableProvider);
return new GithubApi(githubClient, apiUrl, _retryPolicy, multipartUploader);
}
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clientRetryPolicy is created with a service name, but ArchiveUploader and GithubApi are still constructed with _retryPolicy. Any 401s thrown from _retryPolicy.Retry/HttpRetry inside GithubApi/ArchiveUploader will therefore not include the service name (and this also contradicts the PR goal of using per-service policies). Pass clientRetryPolicy to ArchiveUploader and GithubApi here so all GitHub operations use the tagged policy.

This issue also appears in the following locations of the same file:

  • line 45
  • line 56

Copilot uses AI. Check for mistakes.
@offbyone offbyone force-pushed the o1/push-lqwlqnrruqpk branch from f31a39a to 3ea44c3 Compare March 27, 2026 15:39
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 27, 2026

Unit Test Results

    1 files      1 suites   10m 25s ⏱️
1 030 tests 1 030 ✅ 0 💤 0 ❌
1 031 runs  1 031 ✅ 0 💤 0 ❌

Results for commit 9b1a27b.

♻️ This comment has been updated with latest results.

Thread an optional serviceName parameter through RetryPolicy so that 401
Unauthorized errors identify which service/credential failed (e.g.
"Unauthorized (Azure DevOps). Please check your token and try again.").

Production factories (GithubApiFactory, AdoApiFactory,
AdoPipelineTriggerServiceFactory, BbsApiFactory) now create per-service
RetryPolicy instances instead of sharing the DI singleton. Integration tests
also wire service names through their manually-constructed clients.
@offbyone offbyone force-pushed the o1/push-lqwlqnrruqpk branch from 3ea44c3 to 9b1a27b Compare March 27, 2026 16:25
@github-actions
Copy link
Copy Markdown

Code Coverage

Package Line Rate Branch Rate Complexity Health
ado2gh 71% 69% 741
gei 81% 73% 608
bbs2gh 83% 78% 667
Octoshift 84% 74% 1819
Summary 81% (7953 / 9843) 74% (1959 / 2665) 3835

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants